home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
pctjja86.arc
/
GRAPH-2D.BAS
< prev
next >
Wrap
BASIC Source File
|
1985-02-06
|
14KB
|
284 lines
10 ' GRAPH-2D.BAS
15 '
20 ' ***************************
25 ' * Graph-2D *
30 ' * Version 1.0 *
35 ' * (c) F.G. Lether 1985 *
40 ' ***************************
45 '
50 ' This program plots (x,y) points, contained in a
55 ' sequential data file, on the 640 x 200 pixel high
60 ' resolution graphics screen of the IBM Personal
65 ' Computer.
70 '
75 ' Initialization
80 DEFINT I-N : MAXPTS = 500
85 OPTION BASE 1: DIM X.PTS(500),Y.PTS(500)
90 CLS : KEY OFF : WIDTH 40
95 SCREEN 0,1,0,0 : COLOR 7,0,0
100 ' Display introducrory screen
105 FOR K = 1 TO 20
110 LOCATE K + 2,2,0 : PRINT CHR$(176);
115 LOCATE K + 2,38,0 : PRINT CHR$(176)
120 NEXT
125 LOCATE 2,2 : PRINT STRING$(37,176)
130 LOCATE 23,2 : PRINT STRING$(37,176)
135 FOR K = 1 TO 6
140 LOCATE K + 5,10,0 : PRINT CHR$(176);
145 LOCATE K + 5,30,0 : PRINT CHR$(176)
150 NEXT
155 LOCATE 5,10 : PRINT STRING$(21,176)
160 LOCATE 11,10 : PRINT STRING$(21,176)
165 COLOR 15
170 LOCATE 7,17 : PRINT "Graph-2D"
175 LOCATE 9,15 : PRINT "Version 1.0"
180 LOCATE 15,7 : PRINT "Copyright 1985 F.G. Lether"
185 COLOR 0,7
190 LOCATE 19,9 : PRINT " Press Esc key to quit "
195 LOCATE 21,6 : PRINT " Press space bar to continue "
200 COLOR 7,0
205 ' End if Esc key or continue if space bar pressed
210 IF INKEY$ <> "" THEN 210
215 KEYCHR$ = INKEY$ : IF KEYCHR$ = "" THEN 215
220 IF KEYCHR$ = CHR$(27) THEN CLS : WIDTH 80 : END
225 IF KEYCHR$ <> CHR$(32) THEN 215
230 ' Display user input screen
235 CLS : WIDTH 80
240 LOCATE 1,37 : PRINT "Graph-2D"
245 LOCATE 2,37 : PRINT STRING$(8,196)
250 ' Get user data filename and read data
255 LOCATE 5,1,0
260 PRINT "Enter data filename ... ";
265 MAXLEN = 52 : GOSUB 730 : F$ = STG$
270 IF LEFT$(F$,1) = " "OR F$ = "" THEN : GOTO 255
275 IF INSTR(F$,".") = 0 THEN F$ = F$ + ".DAT"
280 ON ERROR GOTO 595
285 OPEN F$ FOR INPUT AS #1
290 LOCATE 25,23
295 PRINT "Please wait, reading input data ...";
300 N.PTS = 0
305 WHILE NOT EOF(1)
310 N.PTS = N.PTS + 1
315 IF N.PTS > MAXPTS THEN 335
320 INPUT #1,X.PTS(N.PTS),Y.PTS(N.PTS)
325 LOCATE 25,60 : PRINT N.PTS;" points";
330 WEND
335 CLOSE #1
340 SCND = 1! : TICS = 18.2 * SCND : SILENT = 32767
345 SOUND SILENT,TICS : SOUND SILENT,1
350 LOCATE 25,23 : PRINT STRING$(49,32);
355 IF 2 <= N.PTS AND N.PTS < MAXPTS THEN 390
360 LOCATE 7,1 : SOUND 40,1
365 PRINT "* Number of points in data file ";
370 PRINT "out of range !"
375 IF N.PTS > MAXPTS THEN PRINT " Too many points"
380 IF N.PTS < 2 THEN PRINT " Less than 2 points"
385 END
390 ON ERROR GOTO 0
395 ' Set default graphics options
400 TITLE$ = "" : XAXIS$ = "" : YAXIS$ = ""
405 AXES$ = "Y" : SCL$ = "N" : ANN$ = "Y" : JSIZE = 1
410 ' Use default graphics options ?
415 LOCATE 7,1 : PRINT "Graph data using defaults ?";
420 PRINT " Enter y or n ... ";
425 MAXLEN = 1 : GOSUB 730 : ANS$ = STG$
430 IF ANS$ = "" OR INSTR("YNyn",ANS$) = 0 THEN GOTO 415
435 IF INSTR("Yy",ANS$) > 0 THEN 565
440 ' Get user's graphics options from keyboard
445 LOCATE 9,1 : PRINT "Enter title of graph ... ";
450 MAXLEN = 52 : GOSUB 730 : TITLE$ = STG$
455 LOCATE 11,1 : PRINT "Enter horizontal axis name ... ";
460 MAXLEN = 34 : GOSUB 730 : XAXIS$ = STG$
465 LOCATE 13,1 : PRINT "Enter vertical axis name ... ";
470 MAXLEN = 19 : GOSUB 730 : YAXIS$ = STG$
475 LOCATE 15,1 : PRINT "Draw axes ? Enter y or n ... ";
480 MAXLEN = 1 : GOSUB 730 : ANS$ = STG$
485 IF ANS$ = "" OR INSTR("YNyn",ANS$) = 0 THEN GOTO 475
490 IF INSTR("Yy",ANS$) > 0 THEN AXES$ = "Y" ELSE AXES$ = "N"
495 LOCATE 17,1
500 PRINT "Use uniform scale ? Enter y or n ... ";
505 MAXLEN = 1 : GOSUB 730 : ANS$ = STG$
510 IF ANS$ = "" OR INSTR("YNyn",ANS$) = 0 THEN GOTO 495
515 IF INSTR("Yy",ANS$) > 0 THEN SCL$ = "Y" ELSE SCL$ = "N"
520 LOCATE 19,1
525 PRINT "Annotate points ? Enter y or n ... ";
530 MAXLEN = 1 : GOSUB 730 : ANS$ = STG$
535 IF ANS$ = "" OR INSTR("YNyn",ANS$) = 0 THEN GOTO 520
540 IF INSTR("Yy",ANS$) > 0 THEN ANN$ = "Y" ELSE ANN$ = "N"
545 IF ANN$ = "N" THEN 565
550 LOCATE 21,1 : PRINT "Enter annotation size ... ";
555 MAXLEN = 2 : GOSUB 730 : JSIZE = VAL(STG$)
560 IF JSIZE < 1 THEN JSIZE = 1
565 LOCATE 25,24
570 PRINT "Please wait, determining graph ...";
575 SOUND SILENT,.5*TICS : SOUND SILENT,1
580 GOSUB 1330 ' plot data data
585 GOTO 90
590 ' Error trapping for input data file
595 SOUND 40,1 : LOCATE 7,1
600 PRINT "* Can't obtain input data ";
605 PRINT "using this filename !"
610 IF ERR = 71 THEN PRINT " Disk not ready ."
615 IF ERR = 53 THEN PRINT " Data file not found ."
620 IF ERR = 64 OR ERR = 76 THEN PRINT " Bad data filename ."
625 PRINT : COLOR 0,7
630 PRINT " Press space bar to retry ";
635 PRINT "or press Esc key to stop "
640 COLOR 7,0 : RESUME 210
645 ON ERROR GOTO 0
650 END
655 ' ----------
660 ' SUBROUTINE - get keyboard input
665 ' ----------
670 ' This subroutine restricts user keyboard input to a
675 ' horizontal box of specified length, the box starting
680 ' at the current position of the cursor. (The code is a
685 ' modified version of some techniques suggested by
690 ' G. Cuellar for controling user input .)
695 '
700 ' Input to this subroutine
705 ' MAXLEN length of input box (# characters allowed)
710 '
715 ' Output from this subroutine
720 ' STG$ characters entered in the box from keyboard
725 '
730 LOCATE ,,0 : SOUND 40,1
735 BOX$ = CHR$(29) + CHR$(176) + CHR$(29)
740 STG$ = ""
745 DEF FN BCK$(STG$) = LEFT$(STG$,LEN(STG$)-1)
750 PRINT STRING$(MAXLEN,CHR$(176));
755 FOR K = 1 TO MAXLEN
760 PRINT CHR$(29);
765 NEXT
770 LOCATE ,,1,7,7 : KEYCHR$ = INPUT$(1)
775 IF KEYCHR$ = CHR$(8) THEN IF STG$ = "" THEN 770 ELSE STG$ = FN BCK$(STG$) : PRINT BOX$; : GOTO 770
780 IF KEYCHR$ = CHR$(13) THEN FOR K = 1 TO MAXLEN - LEN(STG$) : PRINT " "; : NEXT : GOTO 795
785 IF KEYCHR$ < CHR$(32) OR KEYCHR$ > CHR$(126) THEN 770
790 IF LEN(STG$) = MAXLEN THEN 770 ELSE PRINT KEYCHR$; : STG$ = STG$ + KEYCHR$ : GOTO 770
795 LOCATE ,,0
800 RETURN
1000 ' ----------
1010 ' SUBROUTINE - plot data points
1020 ' ----------
1030 ' This subroutine plots (x,y) points on the 640 x 200
1040 ' pixel graphics screen of the IBM PC. It employs the
1050 ' 432 x 180 pixel, centered viewport (104,10)-(535,189).
1060 ' This subroutine requires a color graphics adapter
1070 ' card and BASICA.
1080 '
1090 ' Input arguments to this subroutine are as follows :
1100 ' MAXPTS the maximum number of (x,y) points allowed
1110 ' N.PTS actual number of (x,y)-points to be plotted
1120 ' X.PTS array of abscissa x-points to be plotted
1130 ' Y.PTS array of ordinate y-points to be plotted
1140 ' XAXIS$ label for horizontal x-axis (can be blank)
1150 ' YAXIS$ label for vertical y-axis (can be blank)
1160 ' TITLE$ title for graph (can be blank)
1170 ' AXES$ set to "Y" or "y" to plot axes
1180 ' SCL$ set to "Y" or "y" to use same axis scales
1190 ' ANN$ set to "Y" or "y" to annotate all points
1200 ' JSIZE size of annotation square, e.g. 1,2,3,...
1210 '
1220 ' Restrictions for this subroutine are as follows :
1230 ' MAXPTS should be >= 2, and less than maximum
1240 ' number of anticipated points ever to be plotted.
1250 ' Arrays X.PTS and Y.PTS should be dimensioned to
1260 ' MAXPTS in the calling code.
1270 ' N.PTS must satisfy 2 <= N.PTS <= MAXPTS
1280 ' The respective strings XAXIS$, YAXIS$ and TITLE$
1290 ' should not consist of more than 34, 19 and 52
1300 ' characters, respectively.
1310 '
1320 ' Compute minimum and maximum of x and y points
1330 DEF FN BIG(A,B) = B*ABS(A<B) + A*ABS(A>=B)
1340 DEF FN SMALL(A,B) = B*ABS(A>B) + A*ABS(A<=B)
1350 X.MIN = X.PTS(1) : X.MAX = X.PTS(1)
1360 Y.MIN = Y.PTS(1) : Y.MAX = Y.PTS(1)
1370 FOR K = 2 TO N.PTS
1380 X.MIN = FN SMALL(X.PTS(K),X.MIN)
1390 X.MAX = FN BIG(X.PTS(K),X.MAX)
1400 Y.MIN = FN SMALL(Y.PTS(K),Y.MIN)
1410 Y.MAX = FN BIG(Y.PTS(K),Y.MAX)
1420 NEXT
1430 ' Adjust maximums if uniform scaling
1440 IF SCL$ <> "Y" AND SCL$ <> "y" THEN 1470
1450 IF (X.MAX - X.MIN) > (Y.MAX - Y.MIN) THEN Y.MAX = Y.MIN + (X.MAX - X.MIN) ELSE X.MAX = X.MIN + (Y.MAX - Y.MIN)
1460 ' Set 432 X 180 pixel viewport (104,10)-(535,189)
1470 S.ASPECT = 5! / 12!
1480 Y.PIXELS = 180
1490 X.PIXELS = CINT(Y.PIXELS / S.ASPECT)
1500 I.MIN = 104 : I.MAX = I.MIN + X.PIXELS - 1
1510 J.MIN = 10 : J.MAX = J.MIN + Y.PIXELS - 1
1520 ' If points annotated with squares, adjust viewport size
1530 IF ANN$ <> "Y" AND ANN$ <> "y" THEN 1590
1540 JSIZE = ABS(JSIZE) : JSIZE = FN BIG(JSIZE,1)
1550 ISIZE = CINT(1! + JSIZE / S.ASPECT)
1560 I.MIN = I.MIN + ISIZE : I.MAX = I.MAX - ISIZE
1570 J.MIN = J.MIN + JSIZE : J.MAX = J.MAX - JSIZE
1580 ' World to physical coordinates transformation
1590 J.RANGE = J.MAX - J.MIN : Y.RANGE = Y.MAX - Y.MIN
1600 I.RANGE = I.MAX - I.MIN : X.RANGE = X.MAX - X.MIN
1610 IF Y.MAX > Y.MIN THEN Y.SCALE = J.RANGE / Y.RANGE
1620 IF X.MAX > X.MIN THEN X.SCALE = I.RANGE / X.RANGE
1630 X.ADJ = I.MAX - X.SCALE * X.MAX
1640 Y.ADJ = J.MAX + Y.SCALE * Y.MIN
1650 ' Special case of horizontal or vertical line
1660 IF X.MAX = X.MIN THEN X.SCALE = 0! : X.ADJ = .5 * (I.MAX + I.MIN) : X.MIN = X.MIN - 1 : X.MAX = X.MAX + 1
1670 IF Y.MAX = Y.MIN THEN Y.SCALE = 0! : Y.ADJ = .5 * (J.MAX + J.MIN) : Y.MIN = Y.MIN - 1 : Y.MAX = Y.MAX + 1
1680 DEF FN I.MAP(X) = CINT(X.SCALE * X + X.ADJ)
1690 DEF FN J.MAP(Y) = CINT(Y.ADJ - Y.SCALE * Y)
1700 ' Plot x,y points on high res graphics screen
1710 SCREEN 2
1720 IX = FN I.MAP(X.PTS(1)) : JY = FN J.MAP(Y.PTS(1))
1730 PSET (IX,JY)
1740 IF ANN$ = "Y" OR ANN$ = "y" THEN LINE (IX-ISIZE,JY+JSIZE)-(IX+ISIZE,JY-JSIZE),,BF: PSET (IX,JY)
1750 FOR K = 2 TO N.PTS
1760 IX = FN I.MAP(X.PTS(K)) : JY = FN J.MAP(Y.PTS(K))
1770 LINE -(IX,JY)
1780 IF ANN$ = "Y" OR ANN$ = "y" THEN LINE (IX-ISIZE,JY+JSIZE)-(IX+ISIZE,JY-JSIZE),,BF : PSET (IX,JY)
1790 NEXT
1800 ' If points annotated, restore original viewport parms
1810 IF ANN$ = "Y" OR ANN$ = "y" THEN I.MIN = I.MIN - ISIZE : I.MAX = I.MAX + ISIZE : J.MIN = J.MIN - JSIZE : J.MAX = J.MAX + JSIZE
1820 ' Draw axes if requested and label axis max and mins
1830 IF AXES$ <> "Y" AND AXES$ <> "y" THEN 1980
1840 LINE (I.MIN-2,J.MIN - 1)-(I.MIN-2,J.MAX + 1)
1850 LINE (I.MAX+2,J.MIN - 1)-(I.MAX+2,J.MAX + 1)
1860 LINE (I.MIN-2,J.MIN-1)-(I.MAX+2,J.MIN-1)
1870 LINE (I.MIN-2,J.MAX+1)-(I.MAX+2,J.MAX+1)
1880 FOR K = I.MIN - 2 TO I.MAX + 2 STEP 2
1890 PRESET(K,J.MIN-1) : PRESET(K,J.MAX+1)
1900 NEXT
1910 '' LINE (I.MIN-2,J.MIN-1)-(I.MAX+2,J.MIN-1),,,&HAAAA
1920 '' LINE (I.MIN-2,J.MAX+1)-(I.MAX+2,J.MAX+1),,,&HAAAA
1930 LOCATE 2,4 : PRINT USING "##.##^^^^"; Y.MAX ;
1940 LOCATE 24,4 : PRINT USING "##.##^^^^"; Y.MIN ;
1950 LOCATE 25,13 : PRINT USING "##.##^^^^"; X.MIN ;
1960 LOCATE 25,59 : PRINT USING "##.##^^^^"; X.MAX ;
1970 ' Write graph title (can be blank)
1980 TTL$ = LEFT$(TITLE$,52)
1990 LOCATE 1,(41 - LEN(TTL$) / 2) : PRINT TTL$
2000 ' Write x,y axis labels (can be blank)
2010 XAX$ = LEFT$(XAXIS$,34)
2020 LOCATE 25,(41 - LEN(XAX$) / 2) : PRINT XAX$;
2030 YAX$ = LEFT$(YAXIS$,19)
2040 FOR K = 1 TO LEN(YAX$)
2050 LOCATE (12 - LEN(YAX$) / 2) + K , 12
2060 PRINT MID$(YAX$,K,1);
2070 NEXT
2080 ' Display user prompt beside graph for only DELAY seconds
2090 DEF FN SECONDS = 3600 * VAL(LEFT$(TIME$,2)) + 60 * VAL(MID$(TIME$,4,2)) + VAL(RIGHT$(TIME$,2))
2100 DELAY = 1.5 : TIME0 = FN SECONDS
2110 LOCATE 2,69 : PRINT "************";
2120 LOCATE 3,69 : PRINT "press key e";
2130 LOCATE 4,69 : PRINT "to erase the";
2140 LOCATE 5,69 : PRINT "screen ...";
2150 LOCATE 6,69 : PRINT "************";
2160 IF (FN SECONDS - TIME0) < 3 THEN 2160
2170 FOR K = 0 TO 4
2180 LOCATE 2 + K,69 : PRINT SPACE$(12);
2190 NEXT
2200 ' Wait for E or e key press to return to calling program
2210 KEYSYM$ = INKEY$
2220 IF KEYSYM$ <> "E" AND KEYSYM$ <> "e" THEN 2210 : CLS
2230 RETURN